package ele_handler

import (
	"crypto/md5"
	"fmt"
	"go-yuque/logger"
	"go-yuque/yuque/util"
	"golang.org/x/net/html"
	"net/url"
	"os"
	"path/filepath"
	"strings"
)

func init() {
	registerInitFunc(
		func() YuqueElementHandler {
			h := &cardImageStruct{}
			h.elements = []string{"card"}
			h.attributes = map[string]string{"name": "image"}
			return h
		})
}

type imageBase struct {
	Src  string `json:"src"`
	zoom int    // 缩放比例
}

type cardImageStruct struct {
	BaseHandler
	imageBase
	TaskID       string  `json:"taskId"`
	ClientID     string  `json:"clientId"`
	OriginalType string  `json:"originalType"`
	Width        float64 `json:"width"`
	Height       int     `json:"height"`
	LinkTarget   string  `json:"linkTarget"`
	Name         string  `json:"name"`
	Size         int     `json:"size"`
	From         string  `json:"from"`
	OriginWidth  int     `json:"originWidth"`
	OriginHeight int     `json:"originHeight"`
	Ratio        float64 `json:"ratio"`
	Status       string  `json:"status"`
	Style        string  `json:"style"`
	OcrLocations []struct {
		Text   string `json:"text"`
		X      int    `json:"x"`
		Y      int    `json:"y"`
		Width  int    `json:"width"`
		Height int    `json:"height"`
	} `json:"ocrLocations"`
	ShowTitle  bool   `json:"showTitle"`
	Title      string `json:"title"`
	Rotation   int    `json:"rotation"`
	Crop       []int  `json:"crop"`
	AverageHue string `json:"averageHue"`
	ID         string `json:"id"`
	Margin     struct {
		Top    bool `json:"top"`
		Bottom bool `json:"bottom"`
	} `json:"margin"`
}

func (i *cardImageStruct) doHandle() (err error) {

	if len(i.downloadTocPath) <= 0 {
		logger.Errorf("[cardImage]下载路径为空")
		return fmt.Errorf("下载路径为空")
	}

	err = parseCardJson(i.node, i)
	if err != nil {
		logger.Errorf("[cardImage]解析异常")
		sb := strings.Builder{}
		err = html.Render(&sb, i.node)
		if err != nil {
			i.WriteTextContext(sb.String())
		}
		return err
	}

	err = getImage(i.imageBase, i.Name, i.downloadTocPath, i)

	return
}

func getImage(i imageBase, name, downloadTocPath string, base YuqueElementHandler) (err error) {

	logger.Infof("[getImage]开始处理图片,name:[%s],downloadTocPath:[%s],src:[%s]",
		name, downloadTocPath, i.Src)

	src := i.Src
	if len(src) <= 0 {
		logger.Errorf("[getImage]src为空")
		return fmt.Errorf("[getImage]src为空")
	}

	// 根据 src 计算 hash 值作为文件名
	fileName := md5.Sum([]byte(src))
	fileType := ".png"

	if len(name) > 0 {
		fileType = filepath.Ext(name)
	}

	imageName := fmt.Sprintf("image-%X%s", fileName, fileType)

	baseDir, assetsPath := util.GetAssetsPath(downloadTocPath)

	imagePath := filepath.Join(assetsPath, imageName)

	needDownloadImage := true
	imageState, _ := os.Stat(imagePath)
	if imageState != nil && !imageState.IsDir() {
		logger.Infof("[getImage]图片已存在:[%s]", imagePath)
		needDownloadImage = false
	}

	// 图片已存在，不需要重新下载
	if needDownloadImage {

		browser := util.FakeBrowserStruct{
			Url: src,
		}
		// 下载图片
		imageBytes, err := browser.DoGet()
		if err != nil {
			logger.Errorf("[getImage]下载图片失败,url:[%s],err:%v", src, err)
			return err
		}

		err = os.WriteFile(
			imagePath,
			imageBytes, 0666)
		if err != nil {
			return err
		}
		logger.Infof("[getImage]图片下载到:[%s]", imagePath)
	}

	escapePath := url.PathEscape(fmt.Sprintf("%s.assets", baseDir))

	if i.zoom == 0 {
		i.zoom = 50
	}

	base.WriteTextContext(fmt.Sprintf("<img src=\"%s\" alt=\"%s\" style=\"zoom:%d%%;\" />\n",
		fmt.Sprintf("%s/%s", escapePath, imageName), imageName, i.zoom))

	return
}
